<?php

namespace service\api;


use app\api\model\DevicesApi;
use app\common\model\Member;
use app\common\model\Devices;
use service\Cipher;
use service\InterfaceCode;
use think\facade\Log;
use think\Request;

class AuthConfig
{
    const tms_max_span = 0;        //sig过期时间，0不过期
    public static $did_init_wskeys = [
        //android 正式线
        '1001' => ['key' => '9b4e4f7c7cda5bc0', 'appid' => 1, 'os' => 1],
        // ios 正式线
        '1002' => ['key' => '5A576449B81369E9', 'appid' => 1, 'os' => 2],
    ];
}

//设备ID认证类
class DidToken
{
    public $did;
    public $uid;
    public $tel;
    public $key;
    public $tms;
    public $sign;
    public $imei;
    public $os_type;
    public $appid;
    public $d_name;
    public $app_v;
    public $idfa;
    public $system_v;
    public $app_no;
}

//用户ID认证类
class UidToken
{
    public $uid;
    public $name;
    public $last_did;
    public $last_time;
    public $status;
    public $tel;
    public $ref;
    public $referer_code;
}

class DidCheck    //设备检查
{
    private static $_did_init_wskeys;
    public static $device_info;
    public static $user_info;
    public static $_req_data = null;
    public static $request;

    public static function checkAuth(Request $request, $init = true)    //权限 检查
    {
        self::$request = $request;
        if (!is_numeric($request->param('auth_did'))) {
            self::erroroutput(InterfaceCode::No_such_did, '设备ID不正确！');
        }
        $did = intval($request->param('auth_did'));
        if (!empty($did)) {
            $token          = new DidToken();
            $token->did     = $did;
            $token->tms     = $request->param('tms');
            $token->sign    = $request->param('sign');
            $token->app_no = intval($request->param('app_no'));
        }
        if (!isset($token)) {
            self::erroroutput(InterfaceCode::Did_must_need, InterfaceCode::$message[InterfaceCode::Did_must_need]);
        }
        if (isset(AuthConfig::$did_init_wskeys[$token->did]) && $init)  //app 应用初始化接口
        {
            self::$_did_init_wskeys = true;
        }
        $token = self::callback_getKey($token);
        return self::checkToken($token);
    }

    public static function callback_getKey(DidToken $token)
    {
        if (self::$_did_init_wskeys) {
            if (isset(AuthConfig::$did_init_wskeys[$token->did]))  //使用初始的did和key作为验证
            {
                $t              = AuthConfig::$did_init_wskeys[$token->did];
                $token->key     = $t['key'];
                $token->appid   = $t['appid'];
                $token->os_type = $t['os'];
            }
        }else {
            $devices_model = new Devices();
            $tbl           = $devices_model->where(['did' => $token->did])->find();
            if ($tbl) {
                $token->key      = $tbl->app_key;
                $token->imei     = $tbl->imei;
                $token->os_type  = $tbl->os_type;
                $token->d_name   = $tbl->d_name;
                $token->app_v    = $tbl->app_v;
                $token->idfa     = $tbl->idfa;
                $token->system_v = $tbl->system_v;
                $token->app_no   = $tbl->app_no;
                $token->uid      = 0;
                //保存设备最后一次请求时间最新客户端版本号
                $req_time = strtotime(date('Y-m-d'));
                if ($tbl->req_time != $req_time) {
                    $savedata             = [];
                    $savedata['req_time'] = $req_time;
                    if (!empty(self::$request->app_v) && $tbl->app_v != self::$request->app_v) {
                        $savedata['app_v'] = self::$request->app_v;
                    }
                    $devices_model->where(['did' => $token->did])->update($savedata);
                }
                $users_model = new Member();

                $user_data = $users_model->where(['last_did' => $tbl['did']])->find();
                if (!empty($user_data) && $user_data['id'] > 0) {
                    $token->uid = $user_data['id'];
                    $token->tel = $user_data['mobile'];
                }
            }else {
                self::erroroutput(InterfaceCode::No_such_did, InterfaceCode::$message [InterfaceCode::No_such_did]);
            }
        }
        self::$device_info = $token;
        return $token;
    }

    public static function checkToken(DidToken $token)    //认证签名
    {
        if ($token->tms <= 0) {
        self::erroroutput(InterfaceCode::Invalid_tms_format,
            InterfaceCode::$message[InterfaceCode::Invalid_tms_format]);
    }else {
        if (time() - $token->tms > AuthConfig::tms_max_span && AuthConfig::tms_max_span != 0) {
            self::erroroutput(InterfaceCode::Time_expired, InterfaceCode::$message[InterfaceCode::Time_expired]);
        }
    }
        if (empty($token->key)) {
            self::erroroutput(InterfaceCode::No_such_did, InterfaceCode::$message[InterfaceCode::No_such_did]);
        }
        if (self::authVerify($token)) {
            return $token;
        }
        self::erroroutput(InterfaceCode::Invalid_dsig, InterfaceCode::$message[InterfaceCode::Invalid_dsig]);
    }

    /**
     * 新版验证签名方式
     *
     * @param DidToken $token
     *
     * @return bool
     */
    public static function authVerify(DidToken $token)
    {
        $query = self::$request->get();
        if (!$query) {
            self::erroroutput(InterfaceCode::query_data_error,
                InterfaceCode::$message[InterfaceCode::query_data_error]);
        }
        if (isset($query['sign'])) {
            unset($query['sign']);
        }

        $query        = array_filter($query); // 空参与签名
        $query['key'] = $token->key;
        ksort($query);
        $check_query = http_build_query($query);
        Log::record('==签名==');
        Log::record('源字符串:'.$check_query);
        Log::record('sign:'.substr(md5($check_query), 8, 16));
        Log::record('客户端sign:'.$token->sign);
//                echo substr(md5($check_query), 8, 16);die;
        if (env('app_env') != 'debug') {
            return substr(md5($check_query), 8, 16) == strtolower($token->sign);
        }
        return true;
    }

    public static function erroroutput($code = '', $msg = '')
    {
        $data['code'] = intval($code);
        $data['msg']  = $msg;
        header('Content-Type:application/json;charset=utf-8');
        if (isset(self::$request) && self::$request->param()) {
            $dataLog = json_encode(self::$request->param());
            Log::write('path:['.json_encode(self::$request->param()).']method:['.self::$request->method().']data:['.$dataLog.']');
        }
        exit(json_encode($data, JSON_UNESCAPED_UNICODE));
    }

    public static function checkUserAuth(Request $request)    //用户权限检查
    {
        $uid = $request->param('auth_uid');
        if (!is_numeric($uid)) {
            self::erroroutput(InterfaceCode::No_such_did, '用户ID不正确！');
        }
        $uid = intval($uid);
        if (!empty($uid)) {
            $token           = new UidToken();
            $token->uid      = $uid;
            self::$user_info = $token;
        }
        if (!isset($token)) {
            self::erroroutput(InterfaceCode::Uid_must_need, InterfaceCode::$message[InterfaceCode::Uid_must_need]);
        }
        $tbl = Member::where('id',$uid)->where('status',1)->find();
        if (!$tbl) {
            self::erroroutput(InterfaceCode::No_such_uid, InterfaceCode::$message [InterfaceCode::No_such_uid]);
        }
        if ($tbl->last_did == 0) {
            self::erroroutput(InterfaceCode::No_such_uid, InterfaceCode::$message [InterfaceCode::No_such_uid]);
        }

        if ($tbl->last_did == self::$device_info->did) {
            $token->name     = $tbl->nickname;
            $token->tel      = $tbl->mobile;
            $token->referer_code = $tbl->referer_code;
            $token->ref      = $tbl->ref;
            $token->last_did = $tbl->last_did;
            $token->user_type = $tbl->user_type;
            //            $token->status = $tbl->status;
            //            //保存用户最后一次请求时间
            $req_time = strtotime(date('Y-m-d'));
            if ($tbl->req_time != $req_time) {
                $savedata             = [];
                $savedata['req_time'] = $req_time;
                Member::update($savedata, ['id' => $uid]);
            }
            self::$user_info = $token;
            return $token;
        }

        $tbl_devices = DevicesApi::where('did', $tbl->last_did)->find();
        if ($tbl_devices) {
            self::erroroutput(InterfaceCode::No_such_uid,
                '您的帐号于'.date('Y-m-d H:i', $tbl->req_time).'在另一台'.$tbl_devices->os_type_text.'手机上登录');
        }else {
            self::erroroutput(InterfaceCode::Uid_must_need, InterfaceCode::$message[InterfaceCode::Uid_must_need]);
        }
    }

    /**
     * @param Request $request
     *
     * @return mixed|null|string
     */
    public static function checkLogin()
    {
        $request = self::$request;
        $uid = $request->param('auth_uid');
        if (!is_numeric($uid)) {
            return false;
        }
        $uid = intval($uid);
        $tbl = Member::get($uid);
        if (!$tbl) {
            return false;
        }

        if ($tbl->last_did == 0) {
            return false;
        }

        if ($tbl->last_did == self::$device_info->did) {
            return $uid;
        }
        return false;
    }

    // 参数设置
    public static function req_data(Request $request)
    {
        if (self::$_req_data !== null) {
            return self::$_req_data;
        }

        self::$_req_data = [];
        if (env('APP_ENV') != 'debug') {
            $params = file_get_contents('php://input');
            $req    = json_decode($params, true);
            if (empty($req['data'])) {
                self::erroroutput(InterfaceCode::post_data_error,
                    InterfaceCode::$message [InterfaceCode::post_data_error]);
            }
            $post_data = Cipher::decrypt_openssl($req['data'], self::$device_info->key, '3D3|tE#u)-Wwg!70');
            Log::record('==========请求参数==========');
            Log::record($post_data);
            if (empty($post_data)) {
                self::erroroutput(InterfaceCode::cipher_decrypt_error,
                    InterfaceCode::$message [InterfaceCode::cipher_decrypt_error]);
            }
            $req = json_decode($post_data, true);
            if (empty($req) || is_string($req)) {
                self::erroroutput(InterfaceCode::json_decode_error,
                    InterfaceCode::$message [InterfaceCode::json_decode_error]);
            }
        }else {
            $req = $request->param();
        }

        foreach ($req as $k => $v) {
            if (!is_array($v)) {
                $req[$k] = htmlspecialchars(trim($v));
            }
        }
        self::$_req_data = $req;

        return $req;
    }
}
